import { isObject, compilePath } from './utils';
import Fetch from './Fetch';

const Symbol = require('es6-symbol');
// import {compilePath} from '@/utils/assist'

class ORM {
  constructor({ ajaxBaseUrl = '', ajaxTimeout = 3000, tokenCache = 'session' }) {
    this.module = {};
    this.plugins = [];
    const fetch = new Fetch({ ajaxBaseUrl, ajaxTimeout, tokenCache });
    this.get = this.ajax('get', fetch)();
    this.post = this.ajax('post', fetch)();
    this.delete = this.ajax('delete', fetch)();
    this.patch = this.ajax('patch', fetch)();
    this.put = this.ajax('put', fetch)();
  }

  // 插件装载
  use(plugins) {
    this.plugins.push(plugins);
    this.plugins.forEach((plugin) => {
      const { apply } = plugin;
      apply.call(plugin, this);
    });
  }

  next(module) {
    const self = this;
    let index = 0;
    const nxt = async () => {
      if (index >= module.middlewares.length) {
        return;
      }
      const middleware = module.middlewares[index];
      index++;
      await middleware(module, nxt.bind(self));
    };
    return nxt;
  }

  ajax(method, fetch) {
    return () => (config, ...middlewares) => {
      const source = fetch.CancelToken.source();
      const configObject = isObject(config)
        ? config
        : {
          url: config
        };
      const { url } = configObject;
      const key = Symbol(url);
      this.module[key] = this.module[key] || {
        middlewares: middlewares || [],
        req: {
          body: {}
        },
        res: {}
      };
      const module = this.module[key];
      const self = this;
      const fn = async function funs(params, query) {
        configObject.url = compilePath(url, params);
        module.req.body = params;
        try {
          module.res = await fetch[method](configObject.url, query || params, {
            cancelToken: source.token,
            ...configObject
          });
        } catch (error) {
          console.log('API错误：', error.response);
          throw new Error(error);
        }
        await self.next(module)();
        return module.res;
      };
      fn.source = source;
      return fn;
    };
  }
}

export default ORM;
